Base pointer grab on get-offscreen-parent
authorAlexander Larsson <alexl@redhat.com>
Fri, 5 Jun 2009 12:50:58 +0000 (14:50 +0200)
committerAlexander Larsson <alexl@redhat.com>
Mon, 8 Jun 2009 17:39:14 +0000 (19:39 +0200)
gdk/gdk.symbols
gdk/gdkinternals.h
gdk/gdkwindow.c
gdk/x11/gdkmain-x11.c

index 44cee62b4a93eca2c607433370fd22dfa9456923..d7ec27cec5a5ae3d4d79f76508e1747d1ebf5e07 100644 (file)
@@ -69,7 +69,6 @@ gdk_get_use_xshm
 gdk_set_use_xshm
 #endif
 gdk_keyboard_grab
-gdk_pointer_grab
 #endif
 #endif
 
@@ -715,6 +714,7 @@ gdk_window_set_user_data
 gdk_window_thaw_toplevel_updates_libgtk_only
 gdk_window_thaw_updates
 gdk_window_set_composited
+gdk_pointer_grab
 #endif
 #endif
 
index 288f518f6dc94fa7adf0b7907289bba618cb0dd7..b6da9bb1dd2a62d5bad41a18934cba8b8d2208b2 100644 (file)
@@ -453,6 +453,13 @@ GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
                                              gint             *win_x,
                                              gint             *win_y,
                                              GdkModifierType  *mask);
+GdkGrabStatus _gdk_windowing_pointer_grab    (GdkWindow        *window,
+                                             GdkWindow        *native,
+                                             gboolean          owner_events,
+                                             GdkEventMask      event_mask,
+                                             GdkWindow        *confine_to,
+                                             GdkCursor        *cursor,
+                                             guint32           time);
 void _gdk_windowing_got_event                (GdkDisplay       *display,
                                              GList            *event_link,
                                              GdkEvent         *event,
index 178a4eca202a8440f080af8d8486a73351e4238b..76a9f82aeec15f8c45e3ddb9f4575edcc2ecf1e8 100644 (file)
@@ -8434,6 +8434,112 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
   _gdk_display_enable_motion_hints (display);
 }
 
+static GdkWindow *
+gdk_window_get_offscreen_parent (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindow *res;
+
+  res = NULL;
+  g_signal_emit_by_name (private->impl_window,
+                        "get-offscreen-parent",
+                        &res);
+
+  return res;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
+ *
+ *   Grabs the pointer to a specific window
+ *
+ * Arguments:
+ *   "window" is the window which will receive the grab
+ *   "owner_events" specifies whether events will be reported as is,
+ *     or relative to "window"
+ *   "event_mask" masks only interesting events
+ *   "confine_to" limits the cursor movement to the specified window
+ *   "cursor" changes the cursor for the duration of the grab
+ *   "time" specifies the time
+ *
+ * Results:
+ *
+ * Side effects:
+ *   requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
+ */
+GdkGrabStatus
+gdk_pointer_grab (GdkWindow *    window,
+                 gboolean        owner_events,
+                 GdkEventMask    event_mask,
+                 GdkWindow *     confine_to,
+                 GdkCursor *     cursor,
+                 guint32         time)
+{
+  GdkWindow *native;
+  GdkDisplay *display;
+  GdkGrabStatus res;
+  gulong serial;
+
+  g_return_val_if_fail (window != NULL, 0);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
+
+  /* We need a native window for confine to to work, ensure we have one */
+  if (confine_to)
+    {
+      if (!gdk_window_ensure_native (confine_to))
+       {
+         g_warning ("Can't confine to grabbed window, not native");
+         confine_to = NULL;
+       }
+    }
+
+  /* Non-viewable client side window => fail */
+  if (!_gdk_window_has_impl (window) &&
+      !gdk_window_is_viewable (window))
+    return GDK_GRAB_NOT_VIEWABLE;
+
+  native = gdk_window_get_toplevel (window);
+  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+    {
+      native = gdk_window_get_offscreen_parent (native);
+
+      if (native == NULL ||
+         (!_gdk_window_has_impl (native) &&
+          !gdk_window_is_viewable (native)))
+       return GDK_GRAB_NOT_VIEWABLE;
+
+      native = gdk_window_get_toplevel (native);
+    }
+
+  display = gdk_drawable_get_display (window);
+
+  serial = _gdk_windowing_window_get_next_serial (display);
+
+  res = _gdk_windowing_pointer_grab (window,
+                                    native,
+                                    owner_events,
+                                    event_mask,
+                                    confine_to,
+                                    cursor,
+                                    time);
+
+  if (res == GDK_GRAB_SUCCESS)
+    _gdk_display_add_pointer_grab (display,
+                                  window,
+                                  native,
+                                  owner_events,
+                                  event_mask,
+                                  serial,
+                                  time,
+                                  FALSE);
+
+  return res;
+}
+
 void
 gdk_window_set_has_offscreen_children (GdkWindow *window,
                                       gboolean has_offscreen_children)
index 471a8f2b3c6d2692e8f901861f3016c2e059cae6..f12c7094b832534fedbe1eb94a6c69884af02690 100644 (file)
@@ -138,16 +138,6 @@ gdk_x11_convert_grab_status (gint status)
   return 0;
 }
 
-struct XPointerGrabInfo {
-  GdkDisplay *display;
-  GdkWindow *window;
-  GdkWindow *native_window;
-  gboolean owner_events;
-  gulong serial;
-  guint event_mask;
-  guint32 time;
-};
-
 static void
 has_pointer_grab_callback (GdkDisplay *display,
                           gpointer data,
@@ -156,81 +146,38 @@ has_pointer_grab_callback (GdkDisplay *display,
   _gdk_display_pointer_grab_update (display, serial);
 }
 
-/*
- *--------------------------------------------------------------
- * gdk_pointer_grab
- *
- *   Grabs the pointer to a specific window
- *
- * Arguments:
- *   "window" is the window which will receive the grab
- *   "owner_events" specifies whether events will be reported as is,
- *     or relative to "window"
- *   "event_mask" masks only interesting events
- *   "confine_to" limits the cursor movement to the specified window
- *   "cursor" changes the cursor for the duration of the grab
- *   "time" specifies the time
- *
- * Results:
- *
- * Side effects:
- *   requires a corresponding call to gdk_pointer_ungrab
- *
- *--------------------------------------------------------------
- */
-
 GdkGrabStatus
-gdk_pointer_grab (GdkWindow *    window,
-                 gboolean        owner_events,
-                 GdkEventMask    event_mask,
-                 GdkWindow *     confine_to,
-                 GdkCursor *     cursor,
-                 guint32         time)
+_gdk_windowing_pointer_grab (GdkWindow *window,
+                            GdkWindow *native,
+                            gboolean owner_events,
+                            GdkEventMask event_mask,
+                            GdkWindow *confine_to,
+                            GdkCursor *cursor,
+                            guint32 time)
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
-  GdkWindow *native;
   GdkDisplayX11 *display_x11;
   guint xevent_mask;
   Window xwindow;
   Window xconfine_to;
   Cursor xcursor;
-  unsigned long serial;
   int i;
-  
-  g_return_val_if_fail (window != NULL, 0);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-
-  native = gdk_window_get_toplevel (window);
-
-  /* We need a native window for confine to to work, ensure we have one */
-  if (confine_to)
-    gdk_window_ensure_native (confine_to);
-  
-  /* TODO: What do we do for offscreens and  their children? We need to proxy the grab somehow */
-  if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
-    return GDK_GRAB_SUCCESS;
 
-  if (!_gdk_window_has_impl (window) &&
-      !gdk_window_is_viewable (window))
-    return GDK_GRAB_NOT_VIEWABLE;
-  
   if (confine_to)
     confine_to = _gdk_window_get_impl_window (confine_to);
 
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
 
   cursor_private = (GdkCursorPrivate*) cursor;
-  
+
   xwindow = GDK_WINDOW_XID (native);
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
-  
+
   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
     xconfine_to = None;
   else
     xconfine_to = GDK_WINDOW_XID (confine_to);
-  
+
   if (!cursor)
     xcursor = None;
   else
@@ -238,7 +185,7 @@ gdk_pointer_grab (GdkWindow *         window,
       _gdk_x11_cursor_update_theme (cursor);
       xcursor = cursor_private->xcursor;
     }
-  
+
   xevent_mask = 0;
   for (i = 0; i < _gdk_nenvent_masks; i++)
     {
@@ -250,7 +197,7 @@ gdk_pointer_grab (GdkWindow *         window,
    * hints. If we set a native one we just wouldn't get any events.
    */
   xevent_mask &= ~PointerMotionHintMask;
-  
+
   return_val = _gdk_input_grab_pointer (window,
                                        native,
                                        owner_events,
@@ -258,7 +205,7 @@ gdk_pointer_grab (GdkWindow *         window,
                                        confine_to,
                                        time);
 
-  if (return_val == GrabSuccess || 
+  if (return_val == GrabSuccess ||
       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
       if (!GDK_WINDOW_DESTROYED (native))
@@ -280,22 +227,11 @@ gdk_pointer_grab (GdkWindow *       window,
       else
        return_val = AlreadyGrabbed;
     }
-  
+
   if (return_val == GrabSuccess)
-    {
-      _gdk_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
-                                    window,
-                                    native,
-                                    owner_events,
-                                    event_mask,
-                                    serial,
-                                    time,
-                                    FALSE);
-
-      _gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11), 
-                               has_pointer_grab_callback,
-                               NULL);
-    }
+    _gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
+                             has_pointer_grab_callback,
+                             NULL);
 
   return gdk_x11_convert_grab_status (return_val);
 }